package com.wuhao.jdqlib.utils

import android.Manifest
import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothManager
import android.bluetooth.le.BluetoothLeScanner
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanFilter
import android.bluetooth.le.ScanResult
import android.bluetooth.le.ScanSettings
import android.content.ComponentName
import android.content.Context
import android.content.Context.BIND_AUTO_CREATE
import android.content.Intent
import android.content.ServiceConnection
import android.content.pm.PackageManager
import android.os.Build
import android.os.IBinder
import android.os.ParcelUuid
import android.util.Log
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.core.app.ActivityCompat
import androidx.core.app.ComponentActivity
import androidx.lifecycle.lifecycleScope
import com.coder.vincent.smart_dialog.SmartDialog
import com.coder.vincent.smart_toast.SmartToast
import com.drake.brv.utils.models
import com.drake.channel.receiveEvent
import com.drake.channel.sendEvent
import com.hjq.permissions.OnPermissionCallback
import com.hjq.permissions.XXPermissions
import com.wuhao.jdqlib.R
import com.wuhao.jdqlib.constants.AppConfig
import com.wuhao.jdqlib.constants.BleConfig
import com.wuhao.jdqlib.constants.BleConfig.RX_CHAR_UUID
import com.wuhao.jdqlib.constants.BleConfig.RX_CHAR_UUID2
import com.wuhao.jdqlib.constants.BleConfig.RX_CHAR_UUID_JGQ
import com.wuhao.jdqlib.constants.BleConfig.RX_SERVICE_UUID
import com.wuhao.jdqlib.constants.BleConfig.RX_SERVICE_UUID2
import com.wuhao.jdqlib.constants.BleConfig.RX_SERVICE_UUID_JGQ
import com.wuhao.jdqlib.constants.BleConfig.TX_CHAR_UUID
import com.wuhao.jdqlib.constants.BleConfig.TX_CHAR_UUID2
import com.wuhao.jdqlib.constants.BleConfig.TX_CHAR_UUID_JGQ
import com.wuhao.jdqlib.data.BleBlulletEvent
import com.wuhao.jdqlib.data.BleReceiveDataEvent
import com.wuhao.jdqlib.data.BleStatusChangeEvent
import com.wuhao.jdqlib.data.BleToConnectEvent
import com.wuhao.jdqlib.interf.JdqCallBackNoUI
import com.wuhao.jdqlib.interf.JdqCallback
import com.wuhao.jdqlib.tts.SystemTTSRepository
import com.wuhao.jdqlib.ui.BleListActivity
import com.wuhao.shootclient.ble.UartServiceUART
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.json.JSONObject
import kotlin.math.abs

@SuppressLint("MissingPermission")
class JdqLibUtil(val context: Context, @SuppressLint("RestrictedApi") val activity: ComponentActivity) {
    var callback: JdqCallback? = null
    var isFirstShoot: Boolean = false
    var jdqNumber: Int = 0

    //临时存储，连接成功后使用
    private var temporarilyMac: String? = null
    private var temporarilyName: String? = null

    private val arrayPermission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        listOf(
            android.Manifest.permission.BLUETOOTH_CONNECT,
            android.Manifest.permission.BLUETOOTH_SCAN,
            android.Manifest.permission.ACCESS_FINE_LOCATION
        )
    } else {
        listOf(
            android.Manifest.permission.BLUETOOTH,
            android.Manifest.permission.BLUETOOTH_ADMIN,
            android.Manifest.permission.ACCESS_FINE_LOCATION
        )
    }

    // 创建一个ActivityResultLauncher来启动蓝牙开启请求
    private var enableBtLauncher: ActivityResultLauncher<Intent>? = null
    private var bleAdapter: BluetoothAdapter? = null
    private fun getBluetoothAdapter(): BluetoothAdapter? {
        // 获取BluetoothManager系统服务
        val bluetoothManager: BluetoothManager =
            context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
        // 通过BluetoothManager获取BluetoothAdapter
        val bluetoothAdapter: BluetoothAdapter? = bluetoothManager.adapter

        return bluetoothAdapter
    }

    private var mServiceUART: UartServiceUART? = null

    private val mServiceConnectionUART: ServiceConnection = object : ServiceConnection {
        override fun onServiceConnected(className: ComponentName, rawBinder: IBinder) {
            mServiceUART = (rawBinder as UartServiceUART.LocalBinder).service
            LogUtil.error("onServiceConnected mService= $mServiceUART")
            if (mServiceUART?.initialize() != true) {
                LogUtil.error("Unable to initialize Bluetooth")
            }
        }

        override fun onServiceDisconnected(classname: ComponentName) {
            LogUtil.error("onServiceDisconnected ")
            mServiceUART = null
        }
    }

    private val tts = SystemTTSRepository(context)

    fun initBlue(launcher: ActivityResultLauncher<Intent>) {
        enableBtLauncher = launcher
        LogUtil.error("初始化蓝牙服务")
        val bindIntent = Intent(context, UartServiceUART::class.java)
        context.bindService(bindIntent, mServiceConnectionUART, BIND_AUTO_CREATE)
        bleAdapter = getBluetoothAdapter()
        receiveJdqData()
    }

    fun openBluetooth() {
        checkPermissions()
    }

    private fun checkPermissions(isNoUI: Boolean = false) {
        XXPermissions.with(context)
            .permission(
                arrayPermission
            ).request(object : OnPermissionCallback {
                override fun onGranted(permissions: MutableList<String>, allGranted: Boolean) {
                    if (!allGranted) {
                        SmartToast.emotion().warning(R.string.ble_permission_disagree)
                    } else {
                        checkBleEnable(isNoUI)
                    }
                }

                override fun onDenied(permissions: MutableList<String>, doNotAskAgain: Boolean) {
                    if (doNotAskAgain) {
                        SmartToast.emotion().warning("注意：被永久拒绝授权，会影响系统正常使用")
                        // 如果是被永久拒绝就跳转到应用权限系统设置页面
                        XXPermissions.startPermissionActivity(context, permissions)
                    } else {
                        SmartToast.emotion().warning("系统获取权限失败，会影响系统正常使用")
                    }
                }
            })
    }

    /**
     * 检查蓝牙是否可用、开关是否打开状态
     */
    private fun checkBleEnable(isNoUI: Boolean = false) {
        if (AppConfig.bleConnected) {
            //断开蓝牙确认
            showBleCloseEnsureDialog()
            return
        }
        if (bleAdapter != null) {//是否开启蓝牙
            if (bleAdapter!!.isEnabled) {
                //蓝牙列表
                if (!isNoUI) {
                    //不启用UI的情况下，不跳转至Activity
                    context.startActivity(Intent(context, BleListActivity::class.java))
                }
            } else {
                // 蓝牙没有开启，请求用户开启
                val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
                enableBtLauncher?.launch(enableBtIntent)
            }
        }
    }

    /**
     * 断开蓝牙确认弹窗
     */
    private fun showBleCloseEnsureDialog() {
        val name = getDeviceName()
        SmartDialog.builderOfAcknowledge()
            .message(context.getString(R.string.sure_to_disconnect, name))
            .confirmBtnListener {
                val result = mServiceUART?.disconnect()
                if (result == false) {
                    bleDisConnectRefresh()
                }
                it.dismiss()
            }.build(activity)
            .show()
    }

    private fun bleDisConnectRefresh() {
        //更新UI
        AppConfig.bleName = null
        AppConfig.isConnectBle = false
        //本地调试数据
//        viewModel.addJDQDataToList(TimeUtils.getTime() + "--" + temporarilyName + " 已断开")
        //释放蓝牙资源
        mServiceUART?.close()
    }

    /**
     * 获取蓝牙设备名称
     * 1:记弹器   2：激光枪
     */
    private fun getDeviceName(): String {
        return when (AppConfig.bleType) {
            1 -> context.getString(R.string.ble_device_jdq)
            2 -> context.getString(R.string.ble_device_jgq)
            else -> context.getString(R.string.ble_device)
        }
    }

    /**
     * 接收记弹器数据
     */
    fun receiveJdqData() {
        //接收连接事件
        activity.receiveEvent<BleToConnectEvent> { device ->
            //如果主界面没有打开，就不处理
            handleBleListClickEvent(device)
        }

        //接收蓝牙状态改变事件
        activity.receiveEvent<BleStatusChangeEvent> {
            LogUtil.info("BleStatusChangeEvent：${it.status}")
            when (it.status) {
                BleConfig.BLE_SERVICES_DISCOVERED -> {
                    mServiceUART?.enableTXNotification()
                    //dismissLoading()
                }
                //连接成功
                BleConfig.BLE_CONNECTED -> {
                    //设备名称
                    val name = getDeviceName()
                    val msg = context.getString(R.string.jdq_connect_success, name)
                    SmartToast.emotion().success(msg)
                    callback?.onBlueConnected()
                }
                //断开连接
                BleConfig.BLE_DISCONNECTED -> {
                    val name = getDeviceName()
                    val msg = context.getString(R.string.jdq_disconnect, name)
                    //语音播报
                    SmartToast.emotion().warning(msg)
                    bleDisConnectRefresh()
                    jdqNumber = 0
                    callback?.onBlueDisconnected()
                }
                //不支持蓝牙
                BleConfig.DEVICE_DOES_NOT_SUPPORT_UART -> {
                    //设备名称
                    val name = getDeviceName()
                    val msg = context.getString(R.string.jdq_connect_success, name)
                    SmartToast.emotion().success(msg)
                }
            }
        }

        //接收蓝牙数据
        activity.receiveEvent<BleReceiveDataEvent> { bleData ->
            LogUtil.error("BleReceiveDataEvent：" + bleData.data)
            try {
                when (AppConfig.bleType) {
                    //记弹器数据
                    1 -> handleJiDanQiData(bleData.data)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    //最近一次播报时间
    private var lastCallTimeMillis = 0L
    private var lastReceiveTimeMillis = 0L

    /**
     * 处理蓝牙记弹器发送过来的数据
     * @param data 数据
     */
    fun handleJiDanQiData(data: String) {
        Log.e("jdqStr", data)
        if (data.startsWith("1,")) {//开枪
            val firstValue = data.substring(2)
            val mInt = if (firstValue.length < 9) {
                firstValue.toInt()
            } else {
                999999999
            }

            //满足条件：1.支持记弹器 3.超过阈值
            if (AppConfig.isSupportJdqMode && mInt > AppConfig.vibrationThreshold) {
                if (isFirstShoot == true) {
                    //忽略第一次(拉枪栓)
                    isFirstShoot = false
                    return
                }
                //记弹数量+1
                var shootCount = jdqNumber
                shootCount++
                jdqNumber = shootCount
                //开枪
//                shootFire(AppConfig.targetNumber.toInt())
                // 检查当前播报时间
                val currentTime = System.currentTimeMillis()
                //防止短时间内重复播报
                if (currentTime - lastReceiveTimeMillis >= AppConfig.shootInterval) {
                    //更新最后一次播报时间戳
                    lastReceiveTimeMillis = currentTime
                    //发送数据
                    sendEvent(BleBlulletEvent(jdqNumber))
                    callback?.onDataReceived("$jdqNumber")
                }
            }
        }
        else if (data.contains("alarm")) {//抬枪角度
            val jsonObject = JSONObject(data)
            val secondValue = jsonObject.getDouble("alarm")
            if (abs(secondValue) > AppConfig.angleThreshold) {
                // 检查当前播报时间
                val currentTime = System.currentTimeMillis()
                //防止短时间内重复播报
                if (currentTime - lastCallTimeMillis >= AppConfig.reportInterval) {
                    tts.playText("抬枪过高")
                    SmartToast.emotion().warning(R.string.gun_too_height)
                    //更新最后一次播报时间戳
                    lastCallTimeMillis = currentTime
                    callback?.onError("抬枪过高")
                }
            }
        }
        else if (data.startsWith("010203")) {
            //记弹数量+1
            var shootCount = jdqNumber
            shootCount++
            jdqNumber = shootCount
            // 检查当前播报时间
            val currentTime = System.currentTimeMillis()
            //防止短时间内重复播报
            if (currentTime - lastReceiveTimeMillis >= AppConfig.shootInterval) {
                //更新最后一次播报时间戳
                lastReceiveTimeMillis = currentTime
                //发送数据
                sendEvent(BleBlulletEvent(jdqNumber))
                callback?.onDataReceived("$jdqNumber")
            }
        }
    }

    /**
     * 处理蓝牙点击事件
     */
    private fun handleBleListClickEvent(device: BleToConnectEvent) {
        LogUtil.error("蓝牙点击 mac：" + device.mac)
        try {//可能会发送异常
            if (bleAdapter != null && bleAdapter!!.isEnabled) {
                AppConfig.bleTypeUUID = BleConfig.BLE_UUID
                if (device.name.startsWith("AE")) {//记弹器
                    if (!AppConfig.isSupportJdqMode) {//不支持记弹器
                        SmartToast.emotion().warning(context.getString(R.string.not_support_jdq))
                        return
                    }
                    AppConfig.bleType = 1
                    AppConfig.bleServiceUUID = RX_SERVICE_UUID
                    AppConfig.bleNotifyUUID = TX_CHAR_UUID
                    AppConfig.bleWriteUUID = RX_CHAR_UUID
                    //binding.tvJiDanNum.visibility = View.VISIBLE
                } else if (device.name.startsWith("E104")) {
                    if (!AppConfig.isSupportJdqMode) {//不支持记弹器
                        SmartToast.emotion().warning(context.getString(R.string.not_support_jdq))
                        return
                    }
                    AppConfig.bleType = 1
                    AppConfig.bleServiceUUID = RX_SERVICE_UUID2
                    AppConfig.bleNotifyUUID = TX_CHAR_UUID2
                    AppConfig.bleWriteUUID = RX_CHAR_UUID2
                    //binding.tvJiDanNum.visibility = View.VISIBLE
                } else {
                    AppConfig.bleType = 2
                    AppConfig.bleServiceUUID = RX_SERVICE_UUID_JGQ
                    AppConfig.bleNotifyUUID = TX_CHAR_UUID_JGQ
                    AppConfig.bleWriteUUID = RX_CHAR_UUID_JGQ
                    //binding.tvJiDanNum.visibility = View.GONE
                }

                temporarilyName = device.name
                temporarilyMac = device.mac
                //连接蓝牙
                mServiceUART?.let {
                    //showLoading()
                    mServiceUART!!.connect(device.mac)
                }
            } else {
                SmartToast.emotion().warning(R.string.ble_off_cannot_connect)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /**
     * 注册回调方法
     */
    fun registerCallBack(newCallback: JdqCallback){
        callback = newCallback
    }

    /**
     * 断开蓝牙连接
     */
    fun disConnect(){
        val result = mServiceUART?.disconnect()
        if (result == false) {
            bleDisConnectRefresh()
        }
    }
    /**
     * 关闭蓝牙连接、解绑
     */
    fun cleanResource() {
        mServiceUART?.disconnect()
        context.unbindService(mServiceConnectionUART)
        mServiceUART?.stopSelf()
        mServiceUART = null
        AppConfig.bleMac = null
        AppConfig.bleName = null
    }

    private var bleScanner: BluetoothLeScanner? = null
    private lateinit var scanCallback: ScanCallback
    private var deviceList: ArrayList<ScanResult> = arrayListOf()
    private var callBackNoUI:JdqCallBackNoUI? = null
    private var isScanning:Boolean = false

    fun initBlueNoUI(launcher: ActivityResultLauncher<Intent>){
        initBlue(launcher)
        checkPermissions(true)
        if (bleAdapter == null) {
            SmartToast.emotion().warning("本机不支持BLE")
            return
        }
        bleScanner = bleAdapter!!.bluetoothLeScanner

        // 设置扫描回调
        scanCallback = object : ScanCallback() {
            override fun onScanResult(callbackType: Int, result: ScanResult) {
                super.onScanResult(callbackType, result)
                if (result.device?.name?.isNotEmpty() == true) {
                    processingResults(result)
                }
                if (deviceList.isEmpty()) {
                    callBackNoUI?.scanResult(500,deviceList)
                }else{
                    callBackNoUI?.scanResult(200,deviceList)
                }
            }

            override fun onBatchScanResults(results: List<ScanResult>) {
                deviceList.clear()
                for (result in results) {
                    deviceList.add(result)
                }
                callBackNoUI?.scanResult(200,deviceList)
            }

            override fun onScanFailed(errorCode: Int) {
                super.onScanFailed(errorCode)
                callBackNoUI?.scanResult(500,deviceList)
            }
        }
    }
    /**
     * 更新蓝牙
     */
    private fun processingResults(result: ScanResult) {
        val index =
            deviceList.indexOfFirst { it.device.address == result.device.address }
        if (index != -1) {
            deviceList[index] = result
        } else {
            deviceList.add(result)
        }

        if (deviceList.isNotEmpty()) {

        }
    }

    /**
     * 开始扫描
     */
    fun startBleScan() {
        CoroutineScope(Dispatchers.IO)
            .launch {
                try {
                    callBackNoUI?.scanStatus(1)
                    deviceList.clear()
                    // 创建扫描过滤器
                    val filters: MutableList<ScanFilter> = ArrayList()
                    //只扫描指定打印机
                    val serviceUuid = ParcelUuid.fromString("6e400001-b5a3-f393-e0a9-e50e24dcca9e")
                    val filter = ScanFilter.Builder().setServiceUuid(serviceUuid).build()
                    filters.add(filter)

                    // 创建扫描设置
                    val settings = ScanSettings.Builder()
                        .setScanMode(ScanSettings.SCAN_MODE_BALANCED) // 或其他模式
                        .build()
                    isScanning = true
                    // 开始扫描
                    bleScanner?.startScan(filters, settings, scanCallback)

                    //每次扫描持续15秒
                    delay(15000)

                    //如果扫描结束，没有一个设备就显示缺省
                    if (deviceList.isEmpty()) {
                        callBackNoUI?.scanResult(500,deviceList)
                    }
                    isScanning = false
                    stopBleScan()

                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
    }

    /**
     * 结束扫描
     */
    fun stopBleScan() {
        if (bleAdapter != null && bleAdapter!!.isEnabled) {
            bleScanner?.stopScan(scanCallback)
            callBackNoUI?.scanStatus(2)
        }
    }

    fun connectToBle(device:ScanResult){
        sendEvent(BleToConnectEvent(device.device.address, device.device.name, false))
    }

    fun registeJdqCallBackNoUI(instance:JdqCallBackNoUI){
        callBackNoUI = instance
    }
}